package org.az.netty_study.p13_自定义协议;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.embedded.EmbeddedChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.logging.LoggingHandler;

/**
 * 可不可以创建一个handler给多个channel共用呢?
 * 可以，也不可以，要看handler的用途
 * 如果handler本身有状态，就不能共用
 *  - LengthFieldBasedFrameDecoder，一次没有接收到完整的数据，就把这次接收到的数据保存起来，与下一次接收到的合并
 * 反正，如果handler是无状态的，就可以共用
 *  - LoggingHandler仅打印日志,不保存数据
 * 一般netty会给无状态的handler加@Sharable注解，表明可以共用
 */
public class _2_共享handler {
    public static void main(String[] args) {
        /**
         * 我们自定义的编解码器，应该是可以共用的，因为它没有保存状态，仅仅只能编码和解码
         * 但是CustomizeCodec类不能共享，因为它继承了ByteToMessageCodec
         * ByteToMessageCodec设计之初就是为了缓存上一次不完整的数据，所以其构造方法保证了子类不能是共享的
         * 与ByteToMessageCodec相似的类:MessageToMessageCodec,这个类认为第一次拿到的消息就是一条完整的消息，所以可以共享
         */
        //将handler放在外面，就是共享的handler
        CustomizeCodecSharable codecSharable = new CustomizeCodecSharable();
        LoggingHandler loggingHandler = new LoggingHandler();
        EmbeddedChannel channel = new EmbeddedChannel(
                loggingHandler,
                //帧解码器可以解决黏包半包问题，读取数据不完整就一直等，不向下handler传递，直到读取一条完整的数据
                new LengthFieldBasedFrameDecoder(1024, 16, 4, 0, 0),
                codecSharable
        );
        CustomizeMessage message = new CustomizeMessage()
                .setType((byte) 1)
                .setMsg("hello world");
        //写一个出站消息
        channel.writeOutbound(message);
    }
}
